# coding=utf8

import numpy as np
import networkx as nx
import collections
import logging
logger = logging.getLogger('debug')

import src.cluster.cluster

VECTOR_SIZE = 300
gdf_file = 'data/cluster.gdf'
WORD_NUM_IN_CLUSTER = 3
alpha = 1.2


def display_cluster(graphs, node_word, word_to_vector, node_to_sentence_num):
    '''
    打印聚类结果
    '''
    def distance(point1, point2):
        return np.sqrt(np.sum((point1 - point2)**2))

    def calc_vector_avg(graph):
        '''
        计算所有向量的平均值
        '''
        nodes = graph.nodes()
        vector_avg = np.zeros(VECTOR_SIZE)
        for node in nodes:
            vector_avg += word_to_vector[node_word[node]]
        return vector_avg

    def calc_farthest_vector_from_avg_vector(graph, vector_avg):
        nodes = graph.nodes()
        dist = [distance(word_to_vector[node_word[node]], vector_avg)\
                for node in nodes]
        return max(dist)

    def get_nodes_by_position(graph, position):
        '''
        every node in graph has position, which means before/after the instance
        and the position is defined in src/cluster/create_graph.py
        '''
        nodes = graph.nodes()
        res_nodes = []
        for node in nodes:
            if graph.node[node]['position'] == position:
                res_nodes.append(node)
        return res_nodes

    def plot_cluster(cluster_graph, graphs, cluster_points, nodes_list, node_to_sentence_num):
        '''
        打印两维的点
        '''
        gdf_write = open(gdf_file, 'w')

        gdf_write.write('nodedef>name VARCHAR,label VARCHAR\n')

        for num in xrange(len(graphs)):
            graph = graphs[num]
            words = [node_word[node] for node in graph.nodes()]
            word_to_count = collections.Counter(words)
            
            common_word_to_count = word_to_count.most_common(
                WORD_NUM_IN_CLUSTER if len(word_to_count) >= WORD_NUM_IN_CLUSTER 
                else len(word_to_count))
            common_words = '/'.join([word for word, count in common_word_to_count])
            gdf_write.write(str(num) + ',' + common_words + '\n')
            vector_avg = calc_vector_avg(graph)
            cluster_graph.add_node(num, 
                    center=vector_avg,
                    radius=(calc_farthest_vector_from_avg_vector(graph, vector_avg)+0.1)*alpha,
                    left=get_nodes_by_position(graph, 'left'),
                    right=get_nodes_by_position(graph, 'right')
                    )

        node_list = []  # 将nodes_list中的所有list合并
        for nodes in nodes_list:
            node_list += nodes
        node_list.sort()

        node_to_point = {}
        for cluster_num in xrange(len(nodes_list)):
            for node in nodes_list[cluster_num]:
                node_to_point[node] = cluster_points[cluster_num]

        node_to_graph_num = {}
        for graph_num in xrange(len(graphs)):
            nodes = graphs[graph_num].nodes()
            for node in nodes:
                node_to_graph_num[node] = graph_num

        gdf_write.write('edgedef>node1 VARCHAR,node2 VARCHAR, weight DOUBLE, directed BOOLEAN\n')

        for node_num in xrange(1, len(node_list)):
            prev_node = node_list[node_num - 1]
            cur_node = node_list[node_num]
            if node_to_sentence_num[prev_node] != node_to_sentence_num[cur_node]:
                pass
            else:
                prev_point = node_to_point[prev_node]
                cur_point = node_to_point[cur_node]
                prev_graph_num = node_to_graph_num[prev_node]
                cur_graph_num = node_to_graph_num[cur_node]
                gdf_write.write(str(prev_graph_num) + ',' + \
                        str(cur_graph_num) + ',' + \
                        str(distance(prev_point, cur_point)) + ',' + \
                        'true' + \
                        '\n')
                cluster_graph.add_edge(prev_graph_num, cur_graph_num)
        gdf_write.close()
        
    cluster_points = []
    nodes_list = []
    for graph in graphs:
        vector_avg = calc_vector_avg(graph)
        cluster_points.append(vector_avg)
        nodes_list.append(graph.nodes())
    
    cluster_graph = nx.DiGraph()
    plot_cluster(cluster_graph, graphs, cluster_points, nodes_list, node_to_sentence_num)

    return cluster_graph
